#-*- coding: utf-8 -*-
'''
Created on Oct 27, 2012

@author: bbg
'''

from core.util.debug import Log
from service.protocol.unpay_order_pb2 import UploadOrderRequest
from core.db.shopx.order_main import OrderMain
from core.db.shopx.order_dishes import OrderDishes
from core.db.shopx.order_subdishes import OrderSubdishes
from core.db.shopx.order_payment_mode import OrderPaymentMode
import datetime
from webob import Request, Response
from service.server_config import SrvConfig
from logic.cdkey_mgr import CdkeyManager
from logic.login_session_mgr import LoginSessionMgr

def application(environ, start_response):
    '''
        entrance of apache wsgi application
    '''    
    req = Request(environ)
    res = Response()
    
    OrderService.process(req, res)
    
    return res(environ, start_response)    


class OrderService(object):

    __setup__ = False
    log = None   
    
    @staticmethod
    def process(req, res):      
        if OrderService.__setup__ == False:
            Log.setPath(SrvConfig.getLogPath())
            OrderService.log = Log()            
            OrderService.__setup__ = True         
                

        order_request = UploadOrderRequest()
        try:
            order_bin_data = req.params['file'].data        
       
            if order_bin_data == None:
                OrderService.log.e('OrderService, no binary data')
                res.json = {'ret':-1, 'msg':'invalid params'}
                return
            order_request.ParseFromString(order_bin_data)
        except Exception,e:
            OrderService.log.e('OrderService:process,parse from upload order data failed:%s' % e)
            res.json = {'ret':-1, 'msg':'invalid params'}
            return
                
        dbsession = SrvConfig.getOrderDBSession()
        orderService = OrderService(dbsession)
                
        cdkey = order_request.cdkey
        uuid = order_request.uuid
        username = order_request.username
        token = order_request.token
        
        dbmap = CdkeyManager.getCompanyShopIdPair(cdkey, dbsession)
        if dbmap == None:
            OrderService.log.e('OrderService:process, can not get campany_id and shop_id from cdkey:%s' % cdkey)
            res.json = {'ret':106, 'msg':'can not get campany_id and shop_id from cdkey'}
            return
        
        company_id = dbmap[0]
        shop_id = dbmap[1]
        
        if CdkeyManager.isValid(cdkey, uuid, dbsession) == False:
            OrderService.log.e('OrderService:process invalid cdkey:%s uuid:%s' % (cdkey, uuid))
            res.json = {'ret':106, 'msg':'invalid cdkey'}
            return 
        
        if LoginSessionMgr.isSessionValid(company_id, username, token, dbsession) == False:
            OrderService.log.e('OrderService:process invalid token:%s username:%s' % (username, token))
            res.json = {'ret':107, 'msg':'invalid token'}
            return             
                
        try:            
            #map database            
            cur_year = datetime.datetime.now().strftime("%Y")
            OrderMain.doMapping(company_id, shop_id, cur_year)
            OrderDishes.doMapping(company_id, shop_id, cur_year)
            OrderSubdishes.doMapping(company_id, shop_id, cur_year)
            OrderPaymentMode.doMapping(company_id, shop_id, cur_year)
            OrderService.log.d("OrderService:process, company id:%s, shop id:%s, cur_year:%s" % (company_id, shop_id, cur_year))
                        
            orderid = order_request.orderid
            rows = dbsession.query(OrderMain).filter(OrderMain.order_id == orderid)
                                    
            dbsession.autocommit = False
            dbsession.autoflush = False
                        
            if rows.count() == 0:
                ret = orderService.insertOrder(order_request, dbsession)
                if ret == False:
                    OrderService.log.e("OrderService:process, insert order %s failed" % orderid)
                    res.json = {'ret':-1, 'msg':"order %s insert failed" % orderid}
                    dbsession.rollback()
                else:
                    OrderService.log.d("OrderService:process, sync order %s success" % orderid)            
                    res.json = {'ret':0, 'msg':"order %s sync ok" % orderid}
            else:            
                ret = orderService.replaceOrder(order_request, dbsession)
                if ret == False:
                    OrderService.log.e("OrderService:process, replace order %s failed" % orderid)
                    res.json = {'ret':-1, 'msg':"order %s replace failed" % orderid}
                    dbsession.rollback()
                else:
                    OrderService.log.d("OrderService:process, sync order %s success" % orderid)            
                    res.json = {'ret':0, 'msg':"order %s sync ok" % orderid}                                                                       
                        
            dbsession.close()
        except Exception, e:
            OrderService.log.e('OrderService:process, order %s sync failed:%s' % (orderid, e))
            dbsession.rollback()
            dbsession.close()            
            res.json = {'ret':-1, 'msg':"order %s sync failed, exception" % orderid}        
    
    
    def __init__(self, dbsession):
        self.dbsession = dbsession    
    
    def insertOrder(self, order_request, dbsession):        
        #dbsession.begin() 
        #note: the 'dbsession' has automatically start a transition       
        
        self._prepareInsert(order_request, dbsession)
                        
        if dbsession.flush() == False:
            dbsession.rollback()
            return False
        if dbsession.commit() == False:
            dbsession.rollback()
            return False
        
        return True        
        
    def replaceOrder(self, order_request, dbsession):
        orderid = order_request.orderid
        
        #dbsession.begin()
        
        dbsession.query(OrderMain).filter(OrderMain.order_id == orderid).delete()
        dbsession.query(OrderDishes).filter(OrderDishes.order_id == orderid).delete()
        dbsession.query(OrderSubdishes).filter(OrderSubdishes.order_id == orderid).delete()
        dbsession.query(OrderPaymentMode).filter(OrderPaymentMode.order_id == orderid).delete()
        
        self._prepareInsert(order_request, dbsession)
        
        if dbsession.flush() == False:
            dbsession.rollback()
            return False
        if dbsession.commit() == False:
            dbsession.rollback()
            return False
        
        return True
    
    def _prepareInsert(self, order_request, dbsession):
        orderid = order_request.orderid        
        order_main_input = order_request.order_table_new
        order_dishes_input = order_request.order_table_dishs
        order_subdishes_input = order_request.order_table_subdishs
        order_pay_input = order_request.order_table_pay
                
        nowTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        #order_main table
        order_main = OrderMain()
        order_main.order_id = orderid
        order_main.room_alias_id = order_main_input.room_alias_id
        order_main.room_mark = order_main_input.room_mark
        order_main.person_count = order_main_input.people_count
        order_main.amount = order_main_input.amount
        order_main.room_state = order_main_input.room_state
        order_main.open_time = order_main_input.open_time
        order_main.close_time = order_main_input.close_time
        order_main.final_amount = order_main_input.final_amount
        order_main.discount_rate = order_main_input.discount_rate
        order_main.discount_amount = order_main_input.discount_amount
        order_main.free_amount = order_main_input.free_amount
        order_main.service_fee_rate = order_main_input.service_fee_rate
        order_main.service_amount = order_main_input.service_amount
        order_main.opener = order_main_input.openuser
        order_main.casher = order_main_input.cashuser
        order_main.extra_amount = order_main_input.extra_amount
        order_main.create_time = nowTime
        order_main.modify_time = nowTime
        
        #TODO:
        dbsession.add(order_main)
        OrderService.log.d("OrderService:_prepareInsert, order_main add, orderid %s" % orderid)
                
        insertTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        #order_dishes table
        for dishes in order_dishes_input:
            order_dishes = OrderDishes()
            order_dishes.order_id = orderid
            order_dishes.inner_rank_id = dishes.inner_rank_id
            order_dishes.dish_id = dishes.dish_id
            order_dishes.dish_name = dishes.dish_name
            order_dishes.dish_count = dishes.dish_count
            order_dishes.dish_price = dishes.dish_price
            order_dishes.dish_unit = dishes.dish_unit
            order_dishes.unit_inner_rank_id = dishes.unit_inner_rank_id
            order_dishes.order_time = insertTime
            order_dishes.is_free = dishes.is_free
            order_dishes.is_cook = dishes.is_cook
            order_dishes.order_mode = dishes.order_mode
            order_dishes.order_man = dishes.order_man
            order_dishes.operator = dishes.operator
            order_dishes.discount_rate = dishes.discount_rate
            order_dishes.is_service_charge = dishes.is_service_charge
            order_dishes.cook_content = dishes.cook_content
            order_dishes.cook_extra_charge = dishes.cook_extra_charge
            order_dishes.original_price = dishes.original_price
            order_dishes.stat_class_name = dishes.stat_class
            order_dishes.printer_name = dishes.printer_name
            order_dishes.create_time = nowTime
            order_dishes.modify_time = nowTime            
             
            #TODO:   
            dbsession.add(order_dishes)
        OrderService.log.d("OrderService:_prepareInsert, order_dishes added %d recored" % len(order_dishes_input))
        
        #order_subdishes table
        for subdishes in order_subdishes_input:
            order_subdishes = OrderSubdishes()
            
            order_subdishes.order_id = orderid
            order_subdishes.inner_rank_id = subdishes.dish_id
           
            order_subdishes.dish_id = subdishes.dish_id
            order_subdishes.dish_name = subdishes.dish_name
            order_subdishes.dish_count = subdishes.dish_count
            order_subdishes.dish_price = subdishes.dish_price
            order_subdishes.dish_unit = subdishes.dish_unit
            order_subdishes.unit_inner_rank_id = subdishes.unit_inner_rank_id
            order_subdishes.order_time = insertTime
            order_subdishes.is_cook = subdishes.is_cook
            order_subdishes.order_mode = subdishes.order_mode
            order_subdishes.order_man = subdishes.order_man
            order_subdishes.operator = subdishes.operator
            order_subdishes.discount_rate = subdishes.discount_rate
            order_subdishes.is_service_charge = subdishes.is_service_charge
            order_subdishes.cook_content = subdishes.cook_content
            order_subdishes.cook_extra_charge = subdishes.cook_extra_charge
            order_subdishes.original_price = subdishes.original_price
            order_subdishes.stat_class_name = subdishes.stat_class_name
            order_subdishes.printer_name = subdishes.printer_name               
            order_subdishes.sub_inner_rank_id = subdishes.sub_inner_rank_id
            order_subdishes.create_time = nowTime
            order_subdishes.modify_time = nowTime   
                  
            #TODO:
            dbsession.add(order_subdishes)
            
        OrderService.log.d("OrderService:_prepareInsert, order_subdishes added %d recoreds" % len(order_subdishes_input))

        
        #order_pay table
        for pay in order_pay_input:
            order_pay = OrderPaymentMode()
            
            order_pay.order_id = orderid
            order_pay.payment_name = pay.payment_name
            order_pay.amount = pay.amount
            order_pay.exchange_rate = pay.exchange_rate
            order_pay.original_cash_amount = pay.original_cash_amount
            order_pay.create_time = nowTime
            order_pay.modify_time = nowTime
            
            dbsession.add(order_pay)
            #TODO:       
            OrderService.log.d("OrderService:_prepareInsert, order_pay add")

    
